﻿using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using System.Threading;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using ViewMaker;
using System.Diagnostics;
using CloudStorageLight.Core;
using Ionic.Zip;
using System.Text;
using ViewMaker.Core;
using System.Collections.Generic;
using System.Windows;
using System.Runtime.Serialization.Formatters.Binary;
using iTextSharp.text.pdf;

namespace CloudStorageLight.WpfClient.Tests
{

    /// <summary>
    /// テスト因子
    ///     キャッシュファイルの状態：
    ///         なし、ダウンロード、編集中
    ///     サーバファイルの状態：
    ///         変更なし、変更あり、削除
    /// </summary>
    [TestClass]
    public class CahceTest
    {
        [TestInitialize]
        public void TestSetUp()
        {

            //SynchronizationContext.SetSynchronizationContext(SyncCtx);

            AppViewModel.ExecuteActionAsyncMode = false;
            AppViewModel.ProcessStartMode = false;

            BlobDataManager.Instance = new BlobDataManager();
            BlobDataManager.Instance.LoginAsync(AppUtil.GetAppConfigValue("ServerUrl"), AppUtil.GetAppConfigValue("User"), AppUtil.GetAppConfigValue("Password")).Wait();
            BlobDataManager.Instance.RestoreCachedFile();
            //BlobDataManager.Instance.RestoreFolderMapdFile();
            var setting = BlobDataManager.Instance.LoadSettings();
            BlobDataManager.Instance.SaveSettings(setting);
            var vm = new MyMainVM();
            vm.Init();
        }



        [TestMethod]
        public void キャッシュ確認_通常シナリオ_サーバ変更なし()
        {
            var targetPath = "/TestData/";
            var vm = new MyMainVM();
            vm.Init();

            var targetFolder = GetAndEnsureFolderTree(vm, targetPath);

            //キャッシュクリア
            var file = targetFolder.Files.Where(x => x.Path.EndsWith("ﾄﾞｷｭﾒﾝﾄ.txt")).First();
            vm.ReturnValueAsShowYesNo = true;
            vm.CancelCheckoutCommand.Execute(file);
            var cache = BlobDataManager.Instance.GetCachedFile(file);
            Assert.IsNull(cache);

            try
            {
                //キャッシュ作成(読み取り)
                vm.ReturnValueAsShowYesNo = false;
                vm.ExecuteFileCommand.Execute(file);
                cache = BlobDataManager.Instance.GetCachedFile(file);
                Assert.IsNotNull(cache);
                Assert.IsTrue(cache.IsDownloaded);
                Assert.IsFalse(cache.IsDirty);
                Assert.IsFalse(cache.IsEditing);

                //編集中に
                vm.ReturnValueAsShowYesNo = true;
                vm.ExecuteFileCommand.Execute(file);
                cache = BlobDataManager.Instance.GetCachedFile(file);
                Assert.IsNotNull(cache);
                Assert.IsTrue(cache.IsDownloaded);
                Assert.IsFalse(cache.IsDirty);
                Assert.IsTrue(cache.IsEditing);

                //書き込み
                var data = DateTime.Now.ToString();
                File.WriteAllText(cache.LocalPath, data);
                Assert.IsTrue(cache.IsDirty);

                //キャンセルをNoで中止
                vm.ReturnValueAsShowYesNo = false;
                vm.CancelCheckoutCommand.Execute(file);
                cache = BlobDataManager.Instance.GetCachedFile(file);
                Assert.IsNotNull(cache);
                Assert.IsTrue(cache.IsDownloaded);
                Assert.IsTrue(cache.IsEditing);
                Assert.IsTrue(cache.IsDirty);

                //チェックイン
                vm.ReturnValueAsShowYesNo = true;
                vm.CheckinCommand.Execute(file);
                cache = BlobDataManager.Instance.GetCachedFile(file);
                Assert.IsNotNull(cache);
                Assert.IsTrue(cache.IsDownloaded);
                Assert.IsFalse(cache.IsEditing);
                Assert.IsFalse(cache.IsDirty);

                var svrfile = (FileItem)BlobDataManager.Instance.GetFileAsync(file.Path).Result;
                Assert.AreEqual(svrfile.LastModified, cache.LastModified);
            }
            finally
            {
                vm.ReturnValueAsShowYesNo = true;
                vm.CancelCheckoutCommand.Execute(file);
            }
        }

        [TestMethod]
        public void キャッシュ確認_サーバ変更あり()
        {
            var targetPath = "/TestData/";
            var vm = new MyMainVM();
            vm.Init();

            var targetFolder = GetAndEnsureFolderTree(vm, targetPath);

            //キャッシュクリア
            var file = targetFolder.Files.Where(x => x.Path.EndsWith("ﾄﾞｷｭﾒﾝﾄ.txt")).First();
            vm.ReturnValueAsShowYesNo = true;
            vm.CancelCheckoutCommand.Execute(file);
            var cache = BlobDataManager.Instance.GetCachedFile(file);
            Assert.IsNull(cache);

            var temp = Path.GetTempFileName();
            try
            {
                //編集中
                vm.ReturnValueAsShowYesNo = true;
                vm.ExecuteFileCommand.Execute(file);
                cache = BlobDataManager.Instance.GetCachedFile(file);
                Assert.IsNotNull(cache);
                Assert.IsTrue(cache.IsDownloaded);
                Assert.IsFalse(cache.IsDirty);
                Assert.IsTrue(cache.IsEditing);

                //他の人が更新
                var data = DateTime.Now.ToString();
                File.WriteAllText(cache.LocalPath, data);
                var info = BlobDataManager.Instance.UploadFileAsync(targetPath, cache.LocalPath).Result;

                //書き込み
                data = DateTime.Now.ToString();
                File.WriteAllText(cache.LocalPath, data);
                Assert.IsTrue(cache.IsDirty);
                var moddate = File.GetLastWriteTime(cache.LocalPath);

                //既存ファイル優先ダウンロード
                vm.ReturnValueAsShowYesNo = false;
                vm.ShownMessages.Clear();
                vm.ExecuteFileCommand.Execute(file);
                cache = BlobDataManager.Instance.GetCachedFile(file);
                Assert.AreEqual(File.GetLastWriteTime(cache.LocalPath), moddate);
                Assert.IsTrue(vm.ShownMessages.Any(x => x.Contains("上書き") || x.Contains("overwrite")));
                Assert.AreEqual("", vm.Message);

                //サーバファイル優先ダウンロード
                vm.ReturnValueAsShowYesNo = true;
                vm.ShownMessages.Clear();
                vm.ExecuteFileCommand.Execute(file);
                cache = BlobDataManager.Instance.GetCachedFile(file);
                Assert.AreEqual(File.GetLastWriteTimeUtc(cache.LocalPath), info.LastWriteTime);
                Assert.IsTrue(vm.ShownMessages.Any(x => x.Contains("上書き") || x.Contains("overwrite")));
                Assert.AreEqual("", vm.Message);
            }
            finally
            {
                vm.ReturnValueAsShowYesNo = true;
                vm.CancelCheckoutCommand.Execute(file);
                File.Delete(temp);
            }
        }

        [TestMethod]
        public void キャッシュ確認_サーバ削除()
        {
            var vm = new MyMainVM();
            vm.Init();

            var data = new FileCommandArg();
            data.Path = "/TestData/サブフォルダ/";
            data.Files = new string[] { "/TestData/ﾄﾞｷｭﾒﾝﾄ.txt" };
            vm.CopyCommand.Execute(data);

            var targetPath = "/TestData/サブフォルダ/";

            var targetFolder = GetAndEnsureFolderTree(vm, targetPath);
            //キャッシュクリア
            var file = targetFolder.Files.Where(x => x.Path.EndsWith("ﾄﾞｷｭﾒﾝﾄ.txt")).First();
            vm.ReturnValueAsShowYesNo = true;
            vm.CancelCheckoutCommand.Execute(file);
            var cache = BlobDataManager.Instance.GetCachedFile(file);
            Assert.IsNull(cache);

            var temp = Path.GetTempFileName();
            try
            {
                //編集中
                vm.ReturnValueAsShowYesNo = true;
                vm.ExecuteFileCommand.Execute(file);
                cache = BlobDataManager.Instance.GetCachedFile(file);
                Assert.IsNotNull(cache);
                Assert.IsTrue(cache.IsDownloaded);
                Assert.IsFalse(cache.IsDirty);
                Assert.IsTrue(cache.IsEditing);

                //他の人が削除
                BlobDataManager.Instance.DeleteAsync(file.Path).Wait();

                //書き込み
                var msg = DateTime.Now.ToString();
                File.WriteAllText(cache.LocalPath, msg);
                Assert.IsTrue(cache.IsDirty);
                var moddate = File.GetLastWriteTime(cache.LocalPath);

                //実行
                vm.ReturnValueAsShowYesNo = true;
                vm.ExecuteFileCommand.Execute(file);
                cache = BlobDataManager.Instance.GetCachedFile(file);
                Assert.IsTrue(vm.Message == "Not found." || vm.Message== "ファイルが見つかりません");

                //チェックイン
                vm.ReturnValueAsShowYesNo = true;
                vm.CheckinCommand.Execute(file);
                Assert.IsTrue(vm.Message == "Not found." || vm.Message == "ファイルが見つかりません");

                //キャンセル(破棄しない)
                vm.ReturnValueAsShowYesNo = false;
                vm.CancelCheckoutCommand.Execute(file);
                cache = BlobDataManager.Instance.GetCachedFile(file);
                Assert.IsNotNull(cache);
                Assert.AreEqual("", vm.Message);

                //キャンセル(破棄する)
                vm.ReturnValueAsShowYesNo = true;
                vm.CancelCheckoutCommand.Execute(file);
                cache = BlobDataManager.Instance.GetCachedFile(file);
                Assert.IsNull(cache);
                Assert.AreEqual("", vm.Message);

            }
            finally
            {
                vm.ReturnValueAsShowYesNo = true;
                vm.CancelCheckoutCommand.Execute(file);
                File.Delete(temp);
                data = new FileCommandArg();
                data.Path = "/TestData/サブフォルダ/";
                data.Files = new string[] { "/TestData/ﾄﾞｷｭﾒﾝﾄ.txt" };
                vm.CopyCommand.Execute(data);
            }
        }


        private DirectoryItem GetAndEnsureFolderTree(MainVM vm, string path)
        {
            try
            {
                DirectoryItem target = vm.Folders[0];
                target.LoadChildrenAsync(true).Wait();

                var subPath = "/";

                foreach (var item in path.Split('/'))
                {
                    if (string.IsNullOrEmpty(item)) continue;
                    subPath = subPath + item + "/";
                    target = target.Folders.Where(x => x.Path == subPath).FirstOrDefault();
                    if (target == null) break;
                    target.LoadChildrenAsync(true).Wait();
                }
                return target;

            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex);
                return null;
            }
        }

    }
}
